﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using G.Model;
using G.Runtime;

namespace G.Model.Runtime.Converters
{
    class GameCommandConverter : ExpandableObjectConverter
    {
        public static Dictionary<string, GameCommand> GetCommands(GameSpaceDef pGame)
        {
            Dictionary<string, GameCommand> result = new Dictionary<string, GameCommand>();
            Type[] types = GameCommand.Commands.ToArray();
            foreach (Type t in types)
            {
                if (typeof(GameCommand).IsAssignableFrom(t) && t != typeof(GameCommand))
                {
                    GameCommand cmd = (GameCommand)Activator.CreateInstance(t, new object[] { pGame });
                    result.Add(t.Name, cmd);
                }
            }

            return result;
        }

        public override bool GetStandardValuesSupported(
                                   ITypeDescriptorContext context)
        {
            return true;
        }

        public override StandardValuesCollection
                             GetStandardValues(ITypeDescriptorContext context)
        {
            object obj = context.Instance;
            HasGameSpaceDef dispatcher = (HasGameSpaceDef)obj;
            Dictionary<string, GameCommand> map = GetCommands(dispatcher.GameDef);
            return new StandardValuesCollection(map.Keys);
        }

        public override bool GetStandardValuesExclusive(
                                   ITypeDescriptorContext context)
        {
            return false;
        }

        public override bool CanConvertTo(ITypeDescriptorContext context,
                                          System.Type destinationType)
        {
            if (destinationType == typeof(GameCommand))
            {
                return true;
            }

            return base.CanConvertTo(context, destinationType);
        }

        public override object ConvertTo(ITypeDescriptorContext context,
                                         CultureInfo culture,
                                         object value,
                                         System.Type destinationType)
        {
            if (destinationType == typeof(System.String) &&
                 value is GameCommand)
            {
                GameCommand so = (GameCommand)value;
                return so.Name;
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }

        public override bool CanConvertFrom(ITypeDescriptorContext context,
                                      System.Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }

            return base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context,
                                      CultureInfo culture, object value)
        {
            object obj = context.Instance;
            HasGameSpaceDef dispatcher = (HasGameSpaceDef)obj;
            if (value is string)
            {
                try
                {
                    string s = (string)value;

                    GameCommand cmd = null;
                    if (s.Length > 0)
                    {
                        IDictionary<string, GameCommand> map = GetCommands(dispatcher.GameDef);
                        if (map.ContainsKey(s))
                        {
                            cmd = map[s];
                        }
                    }

                    return cmd;
                }
                catch
                {
                    throw new ArgumentException(
                        "Can not convert '" + (string)value +
                                           "' to type GameDispatcher");
                }
            }

            return base.ConvertFrom(context, culture, value);
        }

    }
}
